use bevy_ecs::entity::Entity;
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;

/// 类型安全的实体 ID 包装器，用于在 TypeScript 中提供更好的类型安全
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct EntityId {
    raw: u32,
}

#[wasm_bindgen]
impl EntityId {
    /// 创建新的 EntityId
    #[wasm_bindgen(constructor)]
    pub fn new(raw: u32) -> Self {
        Self { raw }
    }

    /// 获取原始的 u32 值
    #[wasm_bindgen(getter)]
    pub fn raw(&self) -> u32 {
        self.raw
    }

    /// 转换为字符串表示
    #[wasm_bindgen(js_name = toString)]
    pub fn to_string(&self) -> String {
        format!("EntityId({})", self.raw)
    }
}

impl From<Entity> for EntityId {
    fn from(entity: Entity) -> Self {
        Self {
            raw: entity.index(),
        }
    }
}

impl From<EntityId> for Entity {
    fn from(entity_id: EntityId) -> Self {
        // 使用 from_raw_u32 方法，它接受 u32 并返回 Option<Entity>
        // 如果转换失败（当 raw 为 u32::MAX 时），我们创建一个默认的 Entity
        Entity::from_raw_u32(entity_id.raw).unwrap_or_else(|| {
            // 创建一个有效的默认 Entity（index 为 0）
            Entity::from_raw_u32(0).unwrap()
        })
    }
}

impl From<u32> for EntityId {
    fn from(raw: u32) -> Self {
        Self { raw }
    }
}

impl From<EntityId> for u32 {
    fn from(entity_id: EntityId) -> Self {
        entity_id.raw
    }
}

/// 用于错误处理的结果类型，提供更好的 TypeScript 类型映射
/// 由于 wasm-bindgen 不支持泛型，我们使用 JsValue 作为数据类型
#[derive(Debug, Clone, Serialize, Deserialize)]
#[wasm_bindgen]
pub struct ApiResult {
    success: bool,
    #[wasm_bindgen(skip)]
    data: Option<serde_json::Value>,
    error: Option<String>,
}

#[wasm_bindgen]
impl ApiResult {
    /// 检查是否成功
    #[wasm_bindgen(getter)]
    pub fn success(&self) -> bool {
        self.success
    }

    /// 获取错误信息
    #[wasm_bindgen(getter)]
    pub fn error(&self) -> Option<String> {
        self.error.clone()
    }

    /// 获取数据作为 JsValue
    #[wasm_bindgen(getter)]
    pub fn data(&self) -> JsValue {
        match &self.data {
            Some(value) => serde_wasm_bindgen::to_value(value).unwrap_or(JsValue::NULL),
            None => JsValue::NULL,
        }
    }
}

impl ApiResult {
    /// 创建成功结果
    pub fn ok<T: Serialize>(data: T) -> Self {
        Self {
            success: true,
            data: serde_json::to_value(data).ok(),
            error: None,
        }
    }

    /// 创建错误结果
    pub fn err(error: String) -> Self {
        Self {
            success: false,
            data: None,
            error: Some(error),
        }
    }

    /// 创建空的成功结果
    pub fn ok_empty() -> Self {
        Self {
            success: true,
            data: None,
            error: None,
        }
    }
}

impl<T: Serialize> From<Result<T, String>> for ApiResult {
    fn from(result: Result<T, String>) -> Self {
        match result {
            Ok(data) => Self::ok(data),
            Err(error) => Self::err(error),
        }
    }
}
